#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "configfile.h"
#include "logtoviewerhandler.h"
#include "vision/visionserver.h"
#include "vision/prconfig.h"
#include "cameraDevice/silicoolcamerafactory.h"
#include "cameraDevice/silicoolcamera.h"
#include "cameraDevice/baslercamera.h"
#include "cameraDevice/hikcammera.h"
#include "../Utilities/uiHelper/uioperation.h"
#include "../Utilities/uiHelper/msgboxmodel.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    // initialize logging system
    QObjectFactory::registerClass<LogCategoryConfig>();
    Logger::getIns()->init(true);

    // initialize config model

    QObjectFactory::registerClass<CameraParameter>();
    QObjectFactory::registerClass<CameraConfig>();
    QObjectFactory::registerClass<PRConfigParameter>();
    QObjectFactory::registerClass<PRConfig>();
    qmlRegisterType<ConfigElementInfo>("ConfigElementType", 1, 0, "ConfigElementType");
    qmlRegisterType<ConfigObject>("ConfigObject", 1, 0, "ConfigObject");
    qRegisterMetaType<ConfigElementInfo::Type>();

    CameraConfig cameraConfig;
    cameraConfig.setObjectName("cameraConfig");
    ConfigFile cameraConfigFile("cameraConfig", &cameraConfig, "cameraConfig.json");
    cameraConfigFile.populate();
    engine.rootContext()->setContextProperty("cameraConfig", &cameraConfig);

    for (int i = 0; i < cameraConfig.cameraParameterArray()->count(); i++) {
        CameraParameter *param = (CameraParameter*)cameraConfig.cameraParameterArray()->getConfig(i);
        cameraList.push_back(param->cameraName());
    }
    PRConfig prConfig;
    prConfig.setObjectName("prConfig");
    ConfigFile prConfigFile("prConfig", &prConfig, "prConfig.json");
    prConfigFile.populate();
    engine.rootContext()->setContextProperty("prConfig", &prConfig);

    // End of initializing config model

    // Vision Server QTRO
    auto server = new VisionServer;
    QRemoteObjectHost host;
    host.setHostUrl(QUrl("local:visionServer"));
    host.enableRemoting(server);
    // End of Vision Server QTRO

    //UI object
    qRegisterMetaType<MsgBoxItem>();
    qRegisterMetaType<MsgBoxIcon::Icon>();
    qmlRegisterType<MsgBoxIcon>("MsgBoxIcon", 1, 0, "MsgBoxIcon");
    MsgBoxModel msgBoxModel;
    UIOperation::getIns()->init(&msgBoxModel, QThread::currentThreadId());
    engine.rootContext()->setContextProperty("msgBoxModel", &msgBoxModel);
    engine.rootContext()->setContextProperty("uiOperation", UIOperation::getIns());
    //End of UI object

    //Read camera config
    ConfigObjectArray * cameraParamsArray = cameraConfig.cameraParameterArray();
    for (int i = 0; i < cameraParamsArray->count(); i++){
        CameraParameter* parameter = (CameraParameter*) cameraParamsArray->getConfig(i);
        QString cameraName = parameter->cameraName();
        QString cameraType = parameter->cameraType();
        qInfo("Initializing %s ", cameraName.toStdString().c_str());
        SilicoolCamera * scCamera;
        if (!cameraType.compare(parameter->CAMERA_TYPE_HIKVISION))
        {
            scCamera = SilicoolcameraFactory::instance().createSilicoolcamera(SilicoolcameraFactory::HIK, parameter->cameraName());
            scCamera->SCCameraInit(parameter->cameraIP());
            engine.addImageProvider(cameraName, (HIKCamera*)scCamera);
        } else if (!cameraType.compare(parameter->CAMERA_TYPE_BASLER))
        {
            scCamera = SilicoolcameraFactory::instance().createSilicoolcamera(SilicoolcameraFactory::BASLER, parameter->cameraName());
            scCamera->SCCameraInit(parameter->cameraName());
            engine.addImageProvider(cameraName, (BaslerCamera*)scCamera);
        }
        scCamera->setCameraName(cameraName);
        if (i == 0) engine.rootContext()->setContextProperty("camera_1", scCamera);
        else if (i == 1) engine.rootContext()->setContextProperty("camera_2", scCamera);
        else if (i == 2) engine.rootContext()->setContextProperty("camera_3", scCamera);
    }

    //Start to load the main.qml
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    int result = app.exec();
    //Camers close
    SilicoolcameraFactory::instance().stopAllSilicoolCamera();
    return result;
}
